﻿// Copyright (c) MASA Stack All rights reserved.
// Licensed under the Apache License. See LICENSE.txt in the project root for license information.

namespace Masa.Mc.Service.Admin.Application.MessageTasks.Jobs;

public class ExecuteMessageTaskJob : BackgroundJobBase<ExecuteMessageTaskJobArgs>
{
    private readonly IServiceProvider _serviceProvider;

    public ExecuteMessageTaskJob(ILogger<BackgroundJobBase<ExecuteMessageTaskJobArgs>>? logger
        , IServiceProvider serviceProvider) : base(logger)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecutingAsync(ExecuteMessageTaskJobArgs args)
    {
        await using var scope = _serviceProvider.CreateAsyncScope();
        var multiEnvironmentSetter = scope.ServiceProvider.GetRequiredService<IMultiEnvironmentSetter>();
        multiEnvironmentSetter.SetEnvironment(args.Environment);
        var channelRepository = scope.ServiceProvider.GetRequiredService<IChannelRepository>();
        var messageTaskRepository = scope.ServiceProvider.GetRequiredService<IMessageTaskRepository>();
        var messageTaskHistoryRepository = scope.ServiceProvider.GetRequiredService<IMessageTaskHistoryRepository>();
        var eventBus = scope.ServiceProvider.GetRequiredService<IDomainEventBus>();
        var domainService = scope.ServiceProvider.GetRequiredService<MessageTaskDomainService>();
        var messageTaskJobService = scope.ServiceProvider.GetRequiredService<IMessageTaskJobService>();
        var unitOfWork = scope.ServiceProvider.GetRequiredService<IUnitOfWork>();

        var history = await messageTaskHistoryRepository.FindWaitSendAsync(args.MessageTaskId, args.IsTest);

        if (history == null)
        {
            var messageTask = await messageTaskRepository.FindAsync(x => x.Id == args.MessageTaskId, false);
            if (messageTask == null) return;

            Guid userId = Guid.Empty;
            await messageTaskJobService.DisableJobAsync(messageTask.SchedulerJobId, userId);
            return;
        }
        history.SetTaskId(args.TaskId);
        var messageData = await domainService.GetMessageDataAsync(history.MessageTask, history.MessageTask.Variables);
        history.SetSending();

        if (!args.IsTest && !history.MessageTask.SendTime.HasValue)
        {
            history.MessageTask.SetSending();
        }

        await messageTaskHistoryRepository.UpdateAsync(history);
        await unitOfWork.SaveChangesAsync();
        await unitOfWork.CommitAsync();

        var channel = await channelRepository.FindAsync(x => x.Id == history.MessageTask.ChannelId);

        var eto = channel.Type.GetSendMessageEvent(history.MessageTask.ChannelId.Value, messageData, history);
        await eventBus.PublishAsync(eto);
    }
}
